﻿using System;
using weka.core;
using weka.classifiers;
using weka.classifiers.bayes;
using System.Collections.Generic;
using Folder = OMC.DataManagement.Folder;
using MailContent = OMC.DataManagement.MailContent;
using MenuItem = OMC.DataManagement.MenuItem;

namespace OMC.Classification
{
    /// <summary>
    /// an object of this class could manage all the things
    /// which are responsable of classification
    /// </summary>
    /// <remarks>
    /// Copyright 2012 Stefan Lütolf
    /// </remarks>
    public class ClassificationHandler
    {
        private Instances TheRawData;
        private const String TheFilePath = "./BAMailClassData/ARFF/data.arff";
        private DataLoader TheDataLoader { get; set; }
        private DataWriter TheDataWriter { get; set; }
        private const bool IsFiltered = true;
        private const bool IsDefault = false;

        private bool SetUp;
        private bool Trained;

        private Classifier TheClassifier;
        private TextClassifier TheTextClassifier { get; set; }
        private Prediction ThePrediction { get; set; }
        private double[] TheResult;

        /// <summary>
        /// the constructor to create an object
        /// </summary>
        public ClassificationHandler()
        {
            this.clear();
        }

        /// <summary>
        /// to clear all of the data, which are saved
        /// </summary>
        public void clear()
        {
            TheRawData = null;
            SetUp = false;
            Trained = false;
            TheClassifier = new NaiveBayesMultinomialUpdateable();
            TheTextClassifier = new TextClassifier(TheClassifier);
        }

        /// <summary>
        /// to classify a MailContent
        /// </summary>
        /// <param name="inMailToClassify">a MailContent to classify</param>
        /// <param name="inList">a referenced list, to fill in the predicted class</param>
        public void classify(ref MailContent inMailToClassify, ref List<MenuItem> inList)
        {
            if (Trained)
            {
                //Classify Data
                String StringToClassyfy = inMailToClassify.getContent();
                TheResult = TheTextClassifier.classifyMessage(StringToClassyfy);

                //Evaluate the Data
                ThePrediction = new Prediction(TheTextClassifier, ref TheResult);
                //ThePredictedClassName = ThePrediction.getPredictedClassName();
                ThePrediction.getPredictedClassNameList(ref inList);
                //thePrediction.printAllResults();
            }
        }

        /// <summary>
        /// to train the classifier with the Train Dataset
        /// </summary>
        public void trainClassifier()
        {
            if (SetUp)
            {
                TheTextClassifier = new TextClassifier(TheClassifier);
                TheTextClassifier.setTrainingDataset(TheRawData);
                Trained = true;
            }
        }

        /// <summary>
        /// to create Instances of the List, which contains the Folders and
        /// MailContents of the Email Accounts
        /// </summary>
        /// <param name="inList">the referenced list of Folder</param>
        public void createInstances(ref List<Folder> inList)
        {
            foreach (Folder TheFolder in inList)
            {
                TheTextClassifier.addClass(TheFolder.TheFolderName);
            }
            TheTextClassifier.buildAfterClassesAdded();
            foreach (Folder TheFolder in inList)
            {
                foreach (MailContent TheMailContent in TheFolder)
                {
                    TheTextClassifier.addMailData(TheMailContent.getContent(), TheFolder.TheFolderName);
                }
            }
            TheRawData = TheTextClassifier.buildAfterMailDataAdded();
            SetUp = true;
        }

        /// <summary>
        /// to write Instances to a file
        /// </summary>
        public void writeInstance()
        {
            if (SetUp)
            {
                TheDataWriter = new DataWriter(TheRawData, TheFilePath);
                TheDataWriter.DataOutput = IsDefault;
                TheDataWriter.make();
            }
        }

        /// <summary>
        /// to load Instances from a file
        /// </summary>
        public void loadInstance()
        {
            TheDataLoader = new DataLoader(TheFilePath);
            TheRawData = TheDataLoader.load();
            SetUp = true;
        }
    }
}